/**
 * 
 * AxLib
 * 
 * Author: WaveF
 * QQ: 298010937
 * 
 * TODO:
 * v3.2.5
 * - [x] 将注入THIS的行内函数进行提取，以方便日后维护
 * - [x] 增加一个获取当前代码的方法到THIS
 * - [x] 增加显示与隐藏loading的方法到THIS
 * - [x] 修改了处理多个include代码容器的函数名
 * 
 * v3.2.4
 * - [x] 增加获取 view 原生子元素的方法
 * 
 * v3.2.3
 * - [x] 增加从其他文本框导入代码并合并至主代码的处理
 * 
 * v3.2.2
 * - [x] 修复了一个无法正确返回加载文件列表的bug
 * 
 * v3.2.1
 * - [x] THIS 返回文件列表以便调试
 * 
 **/

(function(){

    let axlibPath = getDeploy({ gval: 'AxLib', defaultUrl: 'https://ax.minicg.com/axlib-v3.min.js' });
    let axloaderPath = getDeploy({ gval: 'AxLoader', defaultUrl: 'https://ax.minicg.com/axloader.js' });

    main();

    function main() {
        if (window.AxWebview) return;
        window.AxWebview = { name: 'axwebview', version: '3.2.5', elements: [] };

        if (!window.yepnope) {
            loadJS(axloaderPath, inited);
        } else {
            inited();
        }
    }

    function inited() {

        let webviews = $('.ax-webview');

        $.each(webviews, (i, k) => {
            let preload = [axlibPath]; /* 必须要有至少一个文件来触发complete回调 */
            let files = preload;
            let dPanel = $(k).parent().parent().parent();
            let pid = dPanel.attr('id');
            let html = dPanel.children(`.panel_state`).find('.ax-html').find(`textarea`).val();
            let css = dPanel.children(`.panel_state`).find('.ax-css').find(`textarea`).val();
            let js = dPanel.children(`.panel_state`).find('.ax-javascript').find(`textarea`).val();
            let fileList = dPanel.children(`.panel_state`).find('.ax-files').find(`select option`);

            let vid = $(k).attr('id'); //viewId
            hideViewChildren(vid);
            addLoadingSvg(k);

            $.each(fileList, (m, n) => {
                var url = $(n).val();
                var checked = ($(n).attr('selected')==='selected');
                if (checked) { files.push(url); }
            });

            let formatInlineFunction = function (func) {
                return func.toString().replace(/VID/g, vid).replace(/  /g, '').trim();
            }

            let resetView = function (alpha, pointerEvents) {
                alpha = alpha || 1;
                pointerEvents = pointerEvents || true;
                $('#VID_div, #VID_text').show().css({
                    'opacity': alpha,
                    'pointer-events': pointerEvents ? 'auto' : 'none'
                });
            }

            let getCodes = function () {
                let codes;
                $.each(window.AxWebview.elements, (i,k) => {
                    if (k.view.$().attr('id') == 'VID') { codes = { html: k.html, css: k.css, js: k.js }; }
                });
                return codes;
            }

            let showLoading = function () {
                setTimeout(()=>{ $('#VID').children('.ax-loading').show(); }, 0);
            }

            let hideLoading = function () {
                setTimeout(()=>{ $('#VID').children('.ax-loading').fadeOut(); }, 0);
            }

            html = formatCode(html);
            css  = formatCode(css);
            js   = formatCode(js);
            let includedCodeBoxNames = getIncludedCodeBoxNames(js); // 获取分开 textarea 存放代码的名称
            let injectCode = `;let THIS = {
                dpanel: $axure('#${pid}'),
                view: $axure('#${vid}'),
                files:["${files.join('\",\"')}"],
                resetView: ${formatInlineFunction(resetView)},
                showLoading: ${formatInlineFunction(showLoading)},
                hideLoading: ${formatInlineFunction(hideLoading)},
                getCodes: ${formatInlineFunction(getCodes)}
            };`.replace(/  /g, '').replace(/\n/g, '');
            injectCode = '/* inject begin */\n' + injectCode + '\n/* inject end */\n';
            js = injectCode + getIncludedCodes(includedCodeBoxNames) + '\n' + js;
            js = `(function(){\n${js}\n}());`;

            $('head').append(`<style type="text/css">${css}</style>`);

            AxWebview.elements.push({
                dPanel: $axure(`#${pid}`),
                view: $axure(`#${vid}`),
                html, css, js, files
            });

            yepnope({
                load: files,
                complete: ()=>{
                    $(k).append(html);
                    $(k).append(`<script type="text/javascript">${js}</script>`);
                    $(k).find('.ax-loading').hide();
                }
            });
        });
    }

    function getHostPath() {
        let path = window.location.href;
        let arr = path.split('/');
        arr.pop();
        path = arr.join('/');
        return path;
    }

    function getDeploy(params) {
        let { gval, defaultUrl } = params;
        let deploy = '';
        $axure.internal($ax=>{deploy=$ax.globalVariableProvider.getVariableValue(gval)});
        if (deploy === '') { deploy = defaultUrl; }
        if (deploy.indexOf('{host}')>-1) { deploy = deploy.replace('{host}', getHostPath()); }
        return deploy;
    }

    function formatCode(code) {
        return code.replace(/ /gi, '');
    }

    function loadJS(url,callback) {
        var s = document.createElement('script');
        s.onload = callback||function(){console.log(url+' loaded.')};
        s.setAttribute('src', url);
        document.querySelector('head').appendChild(s);
    }
    
    function addLoadingSvg(target, options) {
        options = options || { color:'#D1D5DB', opacity:0.2, scale:1.2, delay:0, dur:1, blending:'difference' };

        let svg = `
            <svg xmlns="http://www.w3.org/2000/svg" width="38" height="38" viewBox="0 0 38 38" stroke="${options.color}" style="transform:scale(${options.scale});">
                <g fill="none" fill-rule="evenodd">
                    <g transform="translate(1 1)" stroke-width="2">
                        <circle stroke-opacity="${options.opacity}" cx="18" cy="18" r="18"/>
                        <path d="M36 18c0-9.94-8.06-18-18-18">
                            <animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="${options.dur}s" repeatCount="indefinite"/>
                        </path>
                    </g>
                </g>
            </svg>
        `;

        $('head').append(`
            <style>
                html, body { height: 100%; }
                .ax-loading { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; z-index: 9999; mix-blend-mode:${options.blending}; pointer-events:none; }
                .ax-loading-svg { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
            </style>
        `);
        $(target).append(`<div class="ax-loading"><div class="ax-loading-svg">${svg}</div></div>`);

        return svg;
    }

    function getIncludedCodeBoxNames(code, prefix) {
        prefix = prefix || 'include';

        let arr = [];
        let lines = code.split('\n');
        lines = lines.filter(Boolean);

        let keyword = `\/\/@${prefix} `;
        let regx = new RegExp(keyword);

        for (let i=0; i<lines.length; i++) {
            let line = lines[i] || '';
            if (line.indexOf(keyword)==-1) continue;
            let name = line.replace(regx,'').replace(/;/,'').replace(/'/g,'');
            arr.push(name);
        }
        return arr;
    }

    function getIncludedCodes(codeBox) {
        let codes = [];
        for (let i=0; i<codeBox.length; i++) {
            let name = codeBox[i];
            let code = '';
            let target = $axure(`@${name}`).$().find('textarea');
            if (target.length !== 0) {
                code = target.val();
            }
            codes.push(code + '\n');
        }
        return codes.join('\n');
    }

    function hideViewChildren(vid) {
        let viewColorId = vid + '_div';
        let viewColorEl = $('#'+viewColorId);
        let viewTextId = vid + '_text';
        let viewTextEl = $('#'+viewTextId);
        let viewTextHTML = viewTextEl.html();
        if (viewTextHTML.indexOf('<span>')==-1) { viewTextEl.html('<p><span>&nbsp;</span></p>'); }

        viewColorEl.css('visibility', 'visible');
        viewTextEl.css('visibility', 'visible');

        viewColorEl.hide();
        viewTextEl.hide();
    }

}());